/*
Kakine
ActionScript Framework
Copyright © 2011, PUNY, LLC.

This file is part of KAKINE.

KAKINE is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

KAKINE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with KAKINE.  If not, see <http://www.gnu.org/licenses/>.
*/ 
package com.puny.mvc
{
	import com.puny.mvc.helpers.DelayHelper;
	import com.puny.mvc.helpers.FrameHelper;
	import com.puny.mvc.helpers.IHelper;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	
	public class AssetLifeManager extends Object
	{
		private var _owner:DisplayObject;
		private var _ready:Event = new MvcEvent(MvcEvent.READY);
		private var _beforeClose:Event = new MvcEvent(MvcEvent.BEFORE_CLOSE);
		private var _completed:Event = new MvcEvent(MvcEvent.COMPLETED);
		private var _opened:Event = new MvcEvent(MvcEvent.OPENED);
		private var _helper:IHelper;
		private var _closing:Boolean = false;
		public function AssetLifeManager(owner:DisplayObject) {
			_owner = owner;
			super();
		}
		
		private function ownerName():String {
			return "owner:"+_owner+"(" + _owner.name + ")";
		}
		public function ready():void {
			(_owner as IAssetLife).beforeReady();
//			trace(ownerName()+" is ready.");
			DelayHelper.setup(0,null, dispatchReady);
		}
		
		private function dispatchReady():void {
			_owner.dispatchEvent(_ready.clone());
			_closing = false;
			DelayHelper.setup(0,null,innerBeforeOpen);
		}

		private function innerBeforeOpen():void {
			if(_owner == null||_closing) {
				return;
			}
			(_owner as IAssetLife).afterReady();
//			trace(ownerName()+" enters opening animation");
			_helper = FrameHelper.setup(_owner, (_owner as IAssetLife).beforeOpen, (_owner as IAssetLife).procedureOpen, innerAfterOpen);
		}

		private function innerAfterOpen():void {
			_helper = null;
//			trace(ownerName()+" left opening animation");
			_owner.dispatchEvent(_opened.clone());
			DelayHelper.setup(0,null,beginMainFrame);
		}

		private function beginMainFrame():void {
			(_owner as IAssetLife).afterOpen();
			restartMainFrame();
		}

		/**
		 * restart MianFrame loop when the loop was stopped.
		 * @return <code>true</code> if the loop starts.
		 */		
		public function restartMainFrame():Boolean {
			if (_helper != null||_closing) {
				return false;
			}
//			trace(ownerName() + " enters main animation");
			_helper = FrameHelper.setup(_owner, (_owner as IAssetLife).beforeMainFrame, (_owner as IAssetLife).procedureMainFrame, innerAfterMainFrame);
			return true;
		}

		private function innerAfterMainFrame():void {
			_helper = null;
//			trace(ownerName() + " left main animation");
			(_owner as IAssetLife).afterMainFrame();
		}

		/**
		 * This should be invoked when the class is ready to removed from the stage.
		 * procedureOpen, procedureMainFrame should be canceled.
		 * @see com.puny.mvc.BaseObject.procedureOpen
		 * @see com.puny.mvc.BaseObject.procedureMainFrame
		 */
		final public function complete():void {
//			trace(ownerName() + " is going to be completed.");
			if (!_closing) {
				_closing = true;
				if (_helper!= null) {
					trace(ownerName() + " is canceled");
					_helper.cancel();
					_helper = null;
				}
				_helper = FrameHelper.setup(_owner.stage, innerBeforeClose, (_owner as IAssetLife).procedureClose, innerCloseAfter);
			}
		}
		
		private function innerBeforeClose():void {
			(_owner as IAssetLife).beforeClose();
			trace(ownerName() + " dispatches BEFORE_CLOSED event");
			_owner.dispatchEvent(_beforeClose.clone());
		}

		private function innerCloseAfter():void {
			(_owner as IAssetLife).afterClose();
			trace(ownerName() + " dispatches COMPLETED event");
			_owner.dispatchEvent(_completed.clone());
//			_owner = null;
		}
		
		/**
		 * pause a current loop -i.e. procedureOpen or procedureMainFrame
		 * @see com.puny.mvc.resume
		 * @see com.puny.mvc.BaseObject.procedureOpen
		 * @see com.puny.mvc.BaseObject.procedureMainFrame
		 */
		public function pause():void {
			if (_helper != null) {
				_helper.pause();
			}
		}

		/**
		 * resume a paused loop 
		 * @see com.puny.mvc.resume
		 * @see com.puny.mvc.BaseObject.procedureOpen
		 * @see com.puny.mvc.BaseObject.procedureMainFrame
		 */
		public function resume():void {
			if (_helper != null) {
				_helper.resume();
			}
		}
		
		public function cleanUp():void {
			if (_helper != null) {
				_helper.cancel();
			}
			_owner = null;
		}
	}
}